package com.xlh.service.user.impl;

import cn.hutool.core.date.DateException;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.xlh.common.ResultEnum;
import com.xlh.constant.UserConstant;
import com.xlh.dao.user.UserClassMapper;
import com.xlh.dao.user.UserExtendMapper;
import com.xlh.dao.user.UserMapper;
import com.xlh.dao.user.ext.UserClassMapperExt;
import com.xlh.dao.user.ext.UserMapperExt;
import com.xlh.dto.PageDTO;
import com.xlh.dto.course.ChapterBasicInfoDTO;
import com.xlh.dto.course.CourseBasicDTO;
import com.xlh.dto.course.CourseDTO;
import com.xlh.dto.user.*;
import com.xlh.enums.LocalResourcesEnum;
import com.xlh.enums.PermissionEnum;
import com.xlh.enums.SystemConfigEnum;
import com.xlh.enums.course.ChapterEnum;
import com.xlh.enums.course.ChapterTypeEnum;
import com.xlh.enums.course.CourseStatusEnum;
import com.xlh.enums.course.CourseTypeEnum;
import com.xlh.enums.user.*;
import com.xlh.exception.ClassUserException;
import com.xlh.exception.DeleteDealOperatingException;
import com.xlh.exception.common.BadRequestException;
import com.xlh.exception.common.GlobalException;
import com.xlh.exception.common.NotFoundException;
import com.xlh.listener.AsyncTask;
import com.xlh.param.user.*;
import com.xlh.pojo.course.Course;
import com.xlh.pojo.course.CourseExtend;
import com.xlh.pojo.course.CourseTeacher;
import com.xlh.pojo.course.Direction;
import com.xlh.pojo.system.Permission;
import com.xlh.pojo.system.SystemConfig;
import com.xlh.pojo.user.Class;
import com.xlh.pojo.user.*;
import com.xlh.security.CustomUserDetails;
import com.xlh.security.UserInfoHolder;
import com.xlh.service.course.ChapterService;
import com.xlh.service.course.CourseService;
import com.xlh.service.course.DirectionService;
import com.xlh.service.course.TemplateService;
import com.xlh.service.courseTest.ExperimentService;
import com.xlh.service.courseTest.PaperAnswerSheetService;
import com.xlh.service.courseTest.PaperService;
import com.xlh.service.courseTest.PracticeService;
import com.xlh.service.system.OperationService;
import com.xlh.service.system.SystemConfigService;
import com.xlh.service.user.ClassService;
import com.xlh.service.user.UserService;
import com.xlh.support.training.service.TrainingReportService;
import com.xlh.util.BeanUtil;
import com.xlh.virtualization.constant.ContextTypeEnum;
import com.xlh.virtualization.service.ContainerService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户
 * <p>
 * Created by lx on 2019/1/28.
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserMapperExt userMapperExt;

    @Autowired
    private UserClassMapper userClassMapper;

    @Autowired
    private UserClassMapperExt userClassMapperExt;

    @Autowired
    private UserExtendMapper userExtendMapper;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private ClassService classService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private ExperimentService experimentService;

    @Autowired
    private PracticeService practiceService;

    @Autowired
    private PaperAnswerSheetService paperAnswerSheetService;

    @Autowired
    private OperationService operationService;

    @Autowired
    private TemplateService templateService;

    @Autowired
    private UserService userService;

    @Autowired
    private AsyncTask asyncTask;

    @Autowired
    private TrainingReportService trainingReportService;

    @Autowired
    private SessionRegistry sessionRegistry;

    @Autowired
    private PaperService paperService;

    @Autowired
    private ContainerService containerService;

    @Autowired
    private DirectionService directionService;

    @Value("${project.user-destroyed-days}")
    private Integer userDestroyedDays;

    private static final List<String> NAMES = Lists.newArrayList(
            "赵", "蒋", "杨", "李", "周", "吴", "郑", "王", "冯", "陈", "韩", "张", "邹", "宋", "高");

    @Override
    public UserInfoDTO getUserInfo(Long userId, UserStatusEnum userStatusEnum) {
        return queryUserInfos(Lists.newArrayList(userId),
                userStatusEnum == null ? null : Lists.newArrayList(userStatusEnum)
        ).get(0);
    }

    @Override
    public List<UserInfoDTO> queryUserInfos(List<Long> userIds, List<UserStatusEnum> userStatusEnums) {
        // 设置数据库where条件语句的
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        if (CollectionUtils.isNotEmpty(userIds)) {
            criteria.andIdIn(userIds);
        }
        if (CollectionUtils.isNotEmpty(userStatusEnums)) {
            criteria.andStatusIn(userStatusEnums.stream()
                    .map(userStatusEnum -> userStatusEnum.getCode()).collect(Collectors.toList()));
        }

        // 从数据库查询相应的数据
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) {
            throw new NotFoundException("找不到用户信息");
        }
        return convertUserInfoDTOS(users);
    }

    @Override
    public List<User> listUser(List<Long> userIds) {
        List<User> list = Lists.newArrayList();
        UserExample example = new UserExample();
        if (userIds != null && userIds.size() > 0) {
            example.createCriteria().andIdIn(userIds).andStatusEqualTo(UserStatusEnum.NOT_DELETE.getCode());
        } else {
            return list;
        }
        return userMapper.selectByExample(example);
    }

    @Override
    public List<UserInfoDTO> listUser(String userInfo, List<Integer> roles, List<Integer> statusList, Long userId) {
        return userMapperExt.listUser(userInfo, roles, statusList, userId);
    }

    @Override
    public List<User> listUserInfo(String userNumber, UserStatusEnum userStatusEnum) {
        return userMapperExt.getUserInfo(userNumber,
                userStatusEnum == null ? null : userStatusEnum.getCode());
    }

    @Override
    public Map<Long, Long> getCountByClassId(List<Long> classIds) {
        List<UserClass> userClasses = getUserClassLeftUser(classIds);
        if (CollectionUtils.isEmpty(userClasses)) return null;

        return userClasses.stream()
                .collect(Collectors.groupingBy(UserClass::getClassId, Collectors.counting()));
    }

    @Override
    public List<Long> getClassUser(Long classId) {
        UserClassExample example = new UserClassExample();
        example.createCriteria().andClassIdEqualTo(classId).andDeletedEqualTo(false);
        List<UserClass> userClasses = userClassMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(userClasses)) return null;
        return userClasses.stream().map(UserClass::getUserId).collect(Collectors.toList());
    }

    @Override
    public List<Class> listClassIdByStudentId(Long userId) {
        return userClassMapperExt.listClassIdByStudentId(userId);
    }

    public List<Class> listClassIdByStudentIds(List<Long> userIds) {
        return userClassMapperExt.listClassIdByStudentIds(userIds);
    }

    @Override
    public void updateUserInfo(Long userId, UpdateUserInfoParam updateParam) {

        // 参数验证并进行转换
        User user = checkAndConvertUser(userId, updateParam);

        // 修改用户信息
        userMapper.updateByPrimaryKeySelective(user);

    }

    @Override
    public void updateUserPassword(Long userId, String oldPassword, String newPassword) {
        // 检查用户密码、权限
        checkUserPassword(userId, oldPassword, newPassword);

        // 将参数进行转换
        User user = convertUser(userId, newPassword);

        // 修改数据
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteUser(Long courseId, Long classId, List<Long> userIds, Boolean logicDeleted,
                                Boolean errorFlag, Boolean updatePreseted) {

        /**
         * ----------------------删除学生----------------------
         * 1.删除实验报告
         * 2.删除随堂练习答题情况
         * 3.删除虚机、环境实训记录
         * 4.删除当前人信息
         * 5.删除笔记(学习课件笔记、实验笔记)
         * 6.学生是否已学过某章节（我的课程-详情-已学过的章节打对勾）
         * ----------------------删除教师----------------------
         * 1.与‘删除课程’逻辑一致 -> 相当于删除班级、课程、章节、虚机等信息
         * 2.删除报告模板
         * 3.删除当前人信息
         * 4.教师的流水记录
         */

        if (CollectionUtils.isEmpty(userIds)) throw new BadRequestException("请选择删除的用户");

        // 过滤被删除的userId
        List<UserInfoDTO> userInfos = filterDeletedUserIds(userIds);
        if (CollectionUtils.isEmpty(userInfos)) throw new BadRequestException("请正确选择删除的用户");

        // 将用户信息 按照身份 获取教师id、学生id集合
        Map<IdentityEnum, List<Long>> identityUserIdsMap = userInfos.stream()
                .collect(Collectors.groupingBy(o -> IdentityEnum.getByRole(o.getRole()),
                        Collectors.mapping(UserInfoDTO::getId, Collectors.toList())));
        List<Long> teacherIds = CollectionUtils.isNotEmpty(identityUserIdsMap.get(IdentityEnum.TEACHER)) ?
                identityUserIdsMap.get(IdentityEnum.TEACHER) : Lists.newArrayList();
        List<Long> studentIds = CollectionUtils.isNotEmpty(identityUserIdsMap.get(IdentityEnum.STUDENT)) ?
                identityUserIdsMap.get(IdentityEnum.STUDENT) : Lists.newArrayList();
        List<Long> adminIds = CollectionUtils.isNotEmpty(identityUserIdsMap.get(IdentityEnum.ADMIN)) ?
                identityUserIdsMap.get(IdentityEnum.ADMIN) : Lists.newArrayList();

        List<Long> deleteUserIds = Lists.newArrayList();
        deleteUserIds.addAll(teacherIds);
        deleteUserIds.addAll(studentIds);
        deleteUserIds.addAll(adminIds);

        // 获取教师的课程id集合
        List<CourseDTO> courseDTOS = null;
        if (CollectionUtils.isNotEmpty(teacherIds)) {
            courseDTOS = courseService.listCourse(
                    Lists.newArrayList(CourseStatusEnum.SHARED.getCode(), CourseStatusEnum.SAVE.getCode()),
                    null, null, teacherIds, null);
        }

        // 检查错误参数
        checkErrorFlagParam(teacherIds, studentIds, errorFlag, courseDTOS, courseId);

        if (courseId != null && classId != null
                && CollectionUtils.isEmpty(teacherIds) && CollectionUtils.isNotEmpty(studentIds)) {
            // 获取学生有多个班级
            List<Long> studentIdsForMoreClassIds = userService.getStudentMoreClass(classId);
            if (CollectionUtils.isNotEmpty(studentIdsForMoreClassIds)) {
                List<Long> finalStudentIdsForMoreClassIds = studentIdsForMoreClassIds;
                deleteUserIds = deleteUserIds.stream()
                        .filter(userId -> !finalStudentIdsForMoreClassIds.contains(userId))
                        .collect(Collectors.toList());
            }
        }

        // 删除用户
        deleteUser(deleteUserIds, logicDeleted);

        // 删除流水
        operationService.batchDeleteOperation(deleteUserIds, null, EventCodeEnum.LOGIN);

        // 删除教师
        deleteTeacherIds(teacherIds, courseDTOS, errorFlag, logicDeleted, updatePreseted);

        // 删除学生
        deleteStudentId(studentIds, courseId, classId);

        // 删除用户的session
        deleteUserSession(deleteUserIds);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchNaDeleteUser(List<Long> courseId, Long classId, List<Long> userIds, Boolean logicDeleted, Boolean
            errorFlag) {


        if (CollectionUtils.isEmpty(userIds)) throw new BadRequestException("请选择删除的用户");

        // 过滤被删除的userId
        List<UserInfoDTO> userInfos = filterDeletedUserIds(userIds);
        if (CollectionUtils.isEmpty(userInfos)) throw new BadRequestException("请正确选择删除的用户");

        // 将用户信息 按照身份 获取教师id、学生id集合
        Map<IdentityEnum, List<Long>> identityUserIdsMap = userInfos.stream()
                .collect(Collectors.groupingBy(o -> IdentityEnum.getByRole(o.getRole()),
                        Collectors.mapping(UserInfoDTO::getId, Collectors.toList())));
        List<Long> studentIds = CollectionUtils.isNotEmpty(identityUserIdsMap.get(IdentityEnum.STUDENT)) ?
                identityUserIdsMap.get(IdentityEnum.STUDENT) : Lists.newArrayList();

        List<Long> deleteUserIds = Lists.newArrayList();
        deleteUserIds.addAll(studentIds);


        // 检查错误参数
        checkErrorFlagParams(null, studentIds, errorFlag, null, courseId);


        if (classId != null
                && CollectionUtils.isNotEmpty(studentIds)) {
            // 获取学生有多个班级
            List<Long> studentIdsForMoreClassIds = userService.getStudentMoreClass(classId);
            if (CollectionUtils.isNotEmpty(studentIdsForMoreClassIds)) {
                List<Long> finalStudentIdsForMoreClassIds = studentIdsForMoreClassIds;
                deleteUserIds = deleteUserIds.stream()
                        .filter(userId -> !finalStudentIdsForMoreClassIds.contains(userId))
                        .collect(Collectors.toList());
            }
        }

//        // 删除用户
        deleteUser(deleteUserIds, logicDeleted);

        // 删除流水
        operationService.batchDeleteOperation(deleteUserIds, null, EventCodeEnum.LOGIN);


        // 删除学生
        deleteStudentIds(studentIds, courseId, classId);

        // 删除用户的session
        deleteUserSession(deleteUserIds);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> createUser(List<CreateUserParam> params, IdentityEnum identityEnum,
                                 List<Long> courseIds, Long classId, Boolean errorFlag) {

        // 检查参数
        params = checkAndConvertCreateUserParam(params, identityEnum, courseIds, classId, errorFlag);

        if (CollectionUtils.isEmpty(params)) {
            return null;
        }

        // 转换
        List<User> users = BeanUtil.batchTransform(User.class, params);

        // 获取已经在数据库的用户id集合
        List<Long> existUserIds = users.stream()
                .filter(user -> user.getId() != null).map(User::getId).collect(Collectors.toList());

        // 获取需要插入数据库的数据
        users = users.stream()
                .filter(user -> user.getId() == null).collect(Collectors.toList());

        List<Long> insertDBData = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(users)) {
            // 设置头像
            users = convertUser(users);

            // 创建user_extend表
            for (int i = 0; i < users.size(); i++) {
                UserExtend userExtend = BeanUtil.transform(UserExtend.class, params.get(i));
                if (userExtend != null) {
                    try {
                        userExtendMapper.insertSelective(userExtend);
                        users.get(i).setUserExtendId(userExtend.getId());
                    } catch (Exception e) {

                    }
                }
            }

            // 创建user表
            userMapperExt.batchInsertUser(users);
            insertDBData = users.stream().map(User::getId).collect(Collectors.toList());
        }

        insertDBData.addAll(existUserIds);
        return insertDBData;

    }

    @Override
    public void addAssistant(Long coursed, Long userId, Long classId) {
        List<ClassCourse> courseClassDTOS = userMapperExt.queryListCourseClass(coursed);
        List<CourseTeacher> list = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(courseClassDTOS)) {
            for (ClassCourse courseClassDTO : courseClassDTOS) {
                CourseTeacher courseTeacher = new CourseTeacher();
                courseTeacher.setClassId(courseClassDTO.getClassId());
                courseTeacher.setCourseId(coursed);
                courseTeacher.setUserId(userId);
                courseTeacher.setCreateTime(new Date());
                list.add(courseTeacher);
            }
        }
        userMapperExt.saveCourseTeacher(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(Long userId, UserParam param, IdentityEnum identityEnum) {

        // 检查参数
        User dbUser = checkAndSetGetUpdateUserParam(userId, param, identityEnum);

        // 转换
        User user = BeanUtil.transform(User.class, param);
        user.setId(userId);

        // 修改user参数
        userMapper.updateByPrimaryKeySelective(user);

        if (dbUser.getUserExtendId() == null) return;

        // 获取用户额外信息
        UserExtend dbUserExtend = userExtendMapper.selectByPrimaryKey(dbUser.getUserExtendId());
        if (dbUserExtend == null) return;

        // 修改信息
        if (RoleEnum.getByCode(user.getRole()) != RoleEnum.STUDENT) {
            dbUserExtend.setDestroyTime(param.getDestroyTime());
            dbUserExtend.setApplicant(param.getApplicant());
            dbUserExtend.setProvince(param.getProvince());
            dbUserExtend.setSchoolName(param.getSchoolName());
            userExtendMapper.updateByPrimaryKey(dbUserExtend);
        }

        // 配置教师的课程体系权限
        if (identityEnum == IdentityEnum.TEACHER) {
            systemConfigService.insertOrUpdatePermission(
                    Lists.newArrayList(userId), param.getCourseDirectionHideIds(),
                    PermissionEnum.COURSE_DIRECTION_HIDE);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserSelective(Long id, User user) {
        user.setId(id);
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserStatus(List<Long> userIds, UpdateUserStatusParam param) {

        // 获取销毁时间
        Date destroyTime = getDestroyTime(param.getDestroyTimeStr());

        // 检查参数
        List<User> users = checkUpdateUserStatusParam(userIds, param);

        UserStatusEnum statusEnum = UserStatusEnum.getByCode(param.getStatus());

        // 获取教师的班级
        List<Class> classes = classService.queryClass(userIds);

        if (CollectionUtils.isNotEmpty(classes)) {
            // 获取学生
            List<UserInfoDTO> studentUserInfoDTOS = userService.queryClassUser(
                    null, classes.stream().map(Class::getId).collect(Collectors.toList()),
                    UserStatusEnum.ACCOUNT_CANCELLATION == statusEnum ?
                            Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode()) :
                            Lists.newArrayList(UserStatusEnum.ACCOUNT_CANCELLATION.getCode()), false);
            List<User> studentUsers = BeanUtil.batchTransform(User.class, studentUserInfoDTOS);
            users.addAll(studentUsers);
        }

        // 修改用户状态
        User user = new User();
        user.setStatus(param.getStatus());
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdIn(users.stream().map(User::getId).collect(Collectors.toList()));
        userMapper.updateByExampleSelective(user, userExample);

        // 若状态是激活，需要修改user_extend表的销毁时间
        List<User> filterUsers = users.stream()
                .filter(updateUser -> RoleEnum.STUDENT != RoleEnum.getByCode(updateUser.getRole())
                        && UserStatusEnum.NOT_DELETE == statusEnum && updateUser.getUserExtendId() != null)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(filterUsers)) {
            UserExtendExample userExtendExample = new UserExtendExample();
            userExtendExample.createCriteria()
                    .andIdIn(filterUsers.stream().map(User::getUserExtendId).collect(Collectors.toList()));
            List<UserExtend> userExtends = userExtendMapper.selectByExample(userExtendExample);
            if (CollectionUtils.isNotEmpty(userExtends)) {
                userExtends.forEach(userExtend -> {
                    userExtend.setDestroyTime(destroyTime);
                });
                userMapperExt.updateBatchUserExtend(userExtends);
            }
        }

        if (UserStatusEnum.ACCOUNT_CANCELLATION == statusEnum) {
            // 删除用户的session
            deleteUserSession(userIds);
        }

    }

    @Override
    public void RelievingTeaching(Long courseId, Integer userId) {
        userMapperExt.deleteCourseTeacher(userId, courseId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserApplicationDTO createUniversityTeacherParam(CreateUniversityTeacherParam param) {

        UserApplicationDTO result = new UserApplicationDTO();

        if (!Objects.equals(userInfoHolder.getUser().getRole(), RoleEnum.INTERNET_ADMIN.getRoleCode())) {
            // 验证申请码是否正确
            checkInvitationCode(param.getInvitationCode());

            // 检查手机验证码
            if (StringUtils.isBlank(param.getTelephoneNumber())) {
                throw new BadRequestException("手机号必填");
            }
        }
        // 检查手机验证码
        if (StringUtils.isNotBlank(param.getTelephoneNumber()) && (param.getTelephoneNumber().length() != 11
                || !ReUtil.isMatch(UserConstant.REGEX_NUMBER, param.getTelephoneNumber()))) {
            throw new BadRequestException("手机号不符合11位正确格式，请重新输入");
        }
        // 检查账号是否正确
        if (StringUtils.isNotBlank(param.getUserNumber())) {
            UserExample userExample = new UserExample();
            userExample.createCriteria().andUserNumberEqualTo(param.getUserNumber())
                    .andStatusNotEqualTo(UserStatusEnum.DELETED.getCode());
            List<User> users = userMapper.selectByExample(userExample);
            if (CollectionUtils.isNotEmpty(users)) {
                throw new GlobalException("当前账号已存在，无法创建账号");
            }
        }

        // 插入用户
        User user = insertUser(param);
        user.setPassword(user.getUserNumber());

        // 将教师添加到结果集中
        result.setTeacherUserInfo(user);

        // 创建学生 并 设置结果集
        List<User> universityStudent = createUniversityStudent(user.getId(), param.getCourseDirectionHideIds());
        result.setStudentUserInfo(CollectionUtils.isNotEmpty(universityStudent) ? universityStudent.get(0) : null);
        result.setStudentUserInfos(universityStudent);

        // 配置教师的权限
        systemConfigService.insertOrUpdatePermission(Lists.newArrayList(user.getId()),
                param.getCourseDirectionHideIds(), PermissionEnum.COURSE_DIRECTION_HIDE);

        return result;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<User> createUniversityStudent(Long userId, List<Integer> courseDirectionHideIds) {

        Map<Long, List<CourseDTO>> map = getUniversityCourse(courseDirectionHideIds);
        if (MapUtils.isEmpty(map)) {
            return null;
        }
        Set<Long> courseIds = Sets.newHashSet();
        map.forEach((directionId, courseDTOS) -> {
            courseDTOS.forEach(courseDTO -> {
                courseIds.add(courseDTO.getId());
            });
        });
        if (CollectionUtils.isEmpty(courseIds)) return null;

        // 转换学生信息
        List<CreateUserParam> excelParams = Lists.newArrayList();
        for (int i = 1; i <= 2; i++) {
            excelParams.add(convertStudent(i));
        }

        // 添加班级
        Class classObj = new Class();
        classObj.setName("模拟班级");
        classObj.setGrade(String.valueOf(DateUtil.thisYear()));
        classObj.setUserId(userId);
        Long classId = classService.createClass(classObj, excelParams);

        // 创建班级和学生和课程的关联
        classService.createClassUser(Lists.newArrayList(courseIds), excelParams, classId, true, userId);

        return BeanUtil.batchTransform(User.class, excelParams);
    }

    @Override
    public PageDTO<UserInfoDTO> listUserByPage(Integer pageNum, Integer pageSize, String userInfo,
                                               RoleEnum roleEnum, IdentityEnum identityEnum) {
        // 检查并且转换参数
        List<Integer> searchRoleIds = checkAndConvertParam(roleEnum, identityEnum);
        // 设置搜索的用户状态
        List<Integer> userStatusList = Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode(),
                UserStatusEnum.ACCOUNT_CANCELLATION.getCode());
        if (CollectionUtils.isEqualCollection(searchRoleIds, identityEnum.getReleaseVersionRoles())
                && RoleEnum.INTERNET_ADMIN != RoleEnum.getByCode(userInfoHolder.getUser().getRole())) {
            userStatusList = Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode());
        }

        // 设置分页并查询数据库
        PageHelper.startPage(pageNum, pageSize);
        List<UserInfoDTO> userInfoDTOS = userMapperExt.listUser(userInfo, searchRoleIds,
                userStatusList, userInfoHolder.getUserId());
        PageInfo<UserInfoDTO> pageInfo = new PageInfo<>(userInfoDTOS);
        pageInfo.setList(convertUserPage(pageInfo.getList(), userInfoHolder.getUserId()));
        return new PageDTO<>(pageInfo);
    }

    @Override
    public PageDTO<UserInfoDTO> listUserOtherTeacherByPage(Integer pageNum, Integer pageSize, Long courseId, String userInfo) {
        // 设置分页并查询数据库
        PageHelper.startPage(pageNum, pageSize);
        List<UserInfoDTO> userInfoDTOS = userMapperExt.listUserOtherTeacher(courseId, userInfo, UserStatusEnum.NOT_DELETE.getCode(), userInfoHolder.getUserId());
        userInfoDTOS.forEach(UserInfoDTO -> {
            if (userInfoHolder.getUserId().equals(UserInfoDTO.getId())) {
                UserInfoDTO.setFalg(1);
            } else {
                UserInfoDTO.setFalg(0);
            }
        });
        PageInfo<UserInfoDTO> pageInfo = new PageInfo<>(userInfoDTOS);
        pageInfo.setList(convertUserPage(userInfoDTOS, userInfoHolder.getUserId()));
        return new PageDTO<>(pageInfo);
    }

    @Override
    public List<User> queryUser(IdentityEnum identityEnum) {
        UserExample example = new UserExample();
        example.createCriteria()
                .andRoleIn(identityEnum.getRoles())
                .andStatusEqualTo(UserStatusEnum.NOT_DELETE.getCode());
        return userMapper.selectByExample(example);
    }

    @Override
    public List<UserClassDTO> queryHistoryClass(String classInfo, Long userId) {
        return userClassMapperExt.queryHistoryClass(classInfo, UserStatusEnum.NOT_DELETE.getCode(),
                RoleEnum.STUDENT.getRoleCode(), userId);
    }

    @Override
    public List<UserClass> listUserClass(Long classId) {
        return userClassMapperExt.queryUserClass(classId);
    }

    @Override
    public void insertBatchUserClass(List<Long> userIds, Long classId) {
        userClassMapperExt.insertBatch(userIds, classId);
    }

    @Override
    public void batchDeleteUserClass(List<Long> classIds, List<Long> userIds, Boolean logicDeleted) {

        UserClassExample example = new UserClassExample();
        UserClassExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        if (CollectionUtils.isNotEmpty(classIds)) {
            criteria.andClassIdIn(classIds);
        }
        if (CollectionUtils.isNotEmpty(userIds)) {
            criteria.andUserIdIn(userIds);
        }

        if (!logicDeleted) {
            userClassMapper.deleteByExample(example);
            return;
        }
        UserClass userClass = new UserClass();
        userClass.setDeleted(true);
        userClassMapper.updateByExampleSelective(userClass, example);
    }

    @Override
    public List<Long> getStudentMoreClass(Long classId) {
        // 获取该班级下的学生信息
        List<UserClass> userClasses = getUserClass(Lists.newArrayList(classId));
        if (CollectionUtils.isEmpty(userClasses)) return null;

        // 将学生id集合获取到
        List<Long> studentIds = userClasses.stream().map(UserClass::getUserId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentIds)) return null;

        // 获取这些学生不在原来的班级
        UserClassExample example = new UserClassExample();
        example.createCriteria().andUserIdIn(studentIds).andClassIdNotEqualTo(classId).andDeletedEqualTo(false);
        userClasses = userClassMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(userClasses)) return null;

        // 将学生有第二班级的学生id获取到
        return userClasses.stream().map(UserClass::getUserId).collect(Collectors.toList());

    }

    @Override
    public List<UserInfoDTO> queryClassUser(List<Long> classIds, String userInfo) {
        if (CollectionUtils.isEmpty(classIds)) {
            throw new BadRequestException();
        }
        List<UserInfoDTO> userInfoDTOS = queryClassUser(userInfo, classIds,
                Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode()), false);
        return convertUserInfoDTO(userInfoDTOS);
    }

    @Override
    public List<UserInfoDTO> queryClassUser(List<Long> classIds, String userInfo, List<Integer> studentIds) {

        List<UserInfoDTO> userInfoDTOS = queryClassUser(userInfo, classIds,
                Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode()), false, studentIds);
        return convertUserInfoDTO(userInfoDTOS);
    }

    @Override
    public List<UserInfoDTO> queryClassUser(
            String userInfo, List<Long> classIds, List<Integer> statusList, Boolean deleted) {
        return userMapperExt.listClassUser(userInfo, statusList, classIds, deleted);
    }

    public List<UserInfoDTO> queryClassUser(
            String userInfo, List<Long> classIds, List<Integer> statusList, Boolean deleted, List<Integer> studentIds) {
        return userMapperExt.listClassUserIds(classIds, userInfo, statusList, studentIds, deleted);
    }

    @Override
    public UserInfoDTO getStudentInfo(String userNumber, Integer identity) {
        UserExample example = new UserExample();
        if (identity == 2) {
            example.createCriteria()
                    .andUserNumberEqualTo(userNumber).andRoleEqualTo(RoleEnum.STUDENT.getRoleCode())
                    .andStatusEqualTo(UserStatusEnum.NOT_DELETE.getCode());
        } else {
            example.createCriteria()
                    .andUserNumberEqualTo(userNumber).andRoleIn(Lists.newArrayList(RoleEnum.TEACHER.getRoleCode(), RoleEnum.UNIVERSITY_TEACHER.getRoleCode(), RoleEnum.MARKET_TEACHER.getRoleCode()))
                    .andStatusEqualTo(UserStatusEnum.NOT_DELETE.getCode());
        }
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(users)) {
            UserInfoDTO transform = BeanUtil.transform(UserInfoDTO.class, users.get(0));
            return convertUserPage(Lists.newArrayList(transform), userInfoHolder.getUserId()).get(0);
        }
        return null;
    }

    @Override
    public void deleteUserSession(List<Long> userIds) {
        List<Object> users = sessionRegistry.getAllPrincipals(); // 获取session中所有的用户信息
        users.forEach(principal -> {
            if (!(principal instanceof CustomUserDetails)) return;

            CustomUserDetails loggedUser = (CustomUserDetails) principal;
            if (!userIds.contains(loggedUser.getUser().getId())) return;

            List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false);
            if (CollectionUtils.isNotEmpty(sessionsInfo)) {
                for (SessionInformation sessionInformation : sessionsInfo) {
                    sessionInformation.expireNow();
                }
            }
        });
    }

    @Override
    public List<UserInfoDTO> queryDefaultClassUser(Long courseId) {
        Class defaultClass = classService.getDefaultClass(courseId);
        if (defaultClass == null) {
            throw new GlobalException("暂无默认班级");
        }
        return userService.queryClassUser(Lists.newArrayList(defaultClass.getId()), null);
    }

    @Override
    public UserConfigDTO queryUserPermission() {

        // 获取课程方向数据
        List<SystemConfig> configs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.SCHOOL_TYPE.getKey()));
        if (CollectionUtils.isEmpty(configs)) {
            throw new NotFoundException("");
        }

        // 获取用户的权限
        List<Permission> permissions = queryUserPermission(userInfoHolder.getUserId());

        // 转换结果集
        return new UserConfigDTO(
                convertUserDirection(
                        configs, permissions.stream().map(Permission::getStatus).collect(Collectors.toList())));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserConfig(UserPermissionParam userPermissionParam) {
        systemConfigService.insertOrUpdatePermission(Lists.newArrayList(userInfoHolder.getUserId()),
                userPermissionParam.getCourseDirectionHideIds(), PermissionEnum.COURSE_DIRECTION_HIDE);
    }

    @Override
    public List<Permission> queryUserPermission(Long userId) {

        // 获取课程方向数据
        List<SystemConfig> systemConfigs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.SCHOOL_TYPE.getKey()));
        if (CollectionUtils.isEmpty(systemConfigs)) {
            throw new NotFoundException("");
        }

        List<Long> userIds = Lists.newArrayList(userId);
        UserInfoDTO userInfo = getUserInfo(userId, null);
        if (Objects.equals(userInfo.getRole(), RoleEnum.STUDENT.getRoleCode())) {
            // 查看学生的所有老师
            List<CourseDTO> courseDTOS = courseService.listRelationCourseForStudent(
                    userInfoHolder.getStudentClassIds());
            if (CollectionUtils.isNotEmpty(courseDTOS)) {
                userIds = courseDTOS.stream().map(CourseDTO::getUserId).distinct().collect(Collectors.toList());
            }
        }

        return convert(systemConfigs, userIds);
    }

    @Override
    public List<String> querySchoolNames() {
        UserExtendExample extendExample = new UserExtendExample();
        extendExample.createCriteria().andSchoolNameIsNotNull();
        List<UserExtend> userExtends = userExtendMapper.selectByExample(extendExample);
        if (CollectionUtils.isEmpty(userExtends)) return null;

        return userExtends.stream()
                .filter(userExtend -> StringUtils.isNotBlank(userExtend.getSchoolName()))
                .map(UserExtend::getSchoolName).distinct().collect(Collectors.toList());
    }

    @Override
    public User getUser(Long userId) {
        return userMapper.selectByPrimaryKey(userId);
    }

    @Override
    public List<UserClass> queryUserClass(List<Long> userIds) {
        UserClassExample example = new UserClassExample();
        example.createCriteria().andUserIdIn(userIds).andDeletedEqualTo(false);
        return userClassMapper.selectByExample(example);
    }

    @Override
    public void updatePermission(List<Long> objIds, PermissionEnum permissionEnum, boolean switchOn) {

        // 查询数据库已有的权限
        List<Permission> permissions = systemConfigService.queryPermission(objIds, permissionEnum);
        Map<Long, Permission> permissionMap = BeanUtil.mapByKey("objId", permissions);

        // 转换
        List<Permission> result = Lists.newArrayList();
        objIds.forEach(objId -> {
            Permission permission = new Permission();
            if (permissionMap.containsKey(objId)) {
                permission.setId(permissionMap.get(objId).getId());
            }
            permission.setObjId(objId);
            permission.setCode(permissionEnum.getCode());
            permission.setStatus(switchOn ? 1 : 0);
            result.add(permission);
        });

        // 插入或修改数据库值
        systemConfigService.insertOrUpdatePermission(result);

    }

    private List<Permission> convert(List<SystemConfig> systemConfigs, List<Long> userIds) {

        // 获取权限控制
        List<Permission> permissions = systemConfigService.queryPermission(
                userIds, PermissionEnum.COURSE_DIRECTION_HIDE);

        List<Integer> configIds = systemConfigs.stream().map(SystemConfig::getId).collect(Collectors.toList());
        Map<Long, List<Permission>> userPermissionMap = BeanUtil.aggByKeyToList("objId", permissions);

        // 获取用户选择的权限
        List<Permission> selectPermission = Lists.newArrayList();
        for (Long userId : userIds) {
            List<Permission> permissionList = userPermissionMap.get(userId);
            List<Integer> selectIds = configIds;
            if (CollectionUtils.isNotEmpty(permissionList)) {
                List<Integer> hideIds = permissionList.stream()
                        .map(Permission::getStatus).collect(Collectors.toList());
                selectIds = configIds.stream()
                        .filter(configId -> !hideIds.contains(configId)).collect(Collectors.toList());
            }

            selectIds.forEach(configId -> {
                Permission permission = new Permission();
                permission.setObjId(userId);
                permission.setStatus(configId);
                selectPermission.add(permission);
            });
        }

        return selectPermission;
    }

    private List<UserInfoDTO> convertUserInfoDTO(List<UserInfoDTO> userInfoDTOS) {
        userInfoDTOS.forEach(userInfoDTO -> {
            SexEnum sexEnum = SexEnum.getByCode(userInfoDTO.getSex());
            if (sexEnum != null) {
                userInfoDTO.setSexName(sexEnum.getMessage());
            }
        });
        return userInfoDTOS;
    }

    private List<User> convertUser(List<User> users) {
        List<SystemConfig> systemConfigs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.USER_ICON.getKey()));
        users.forEach(user -> {
            // 设置头像
            if (CollectionUtils.isNotEmpty(systemConfigs)) {
                user.setIcon(RandomUtil.randomEle(systemConfigs).getKeyValue());
            }
            // 设置密码
            user.setPassword(new BCryptPasswordEncoder().encode(
                    StringUtils.isEmpty(user.getPassword()) ? UserConstant.INIT_PASSWORD : user.getPassword()));
        });
        return users;
    }

    private List<UserInfoDTO> convertUserPage(
            List<UserInfoDTO> userInfoDTOS, Long currentUserId) {

        // 获取用户权限控制
        List<Permission> permissions = systemConfigService.queryPermission(
                userInfoDTOS.stream().map(UserInfoDTO::getId).collect(Collectors.toList()),
                PermissionEnum.COURSE_DIRECTION_HIDE);
        Map<Long, List<Permission>> userPermissionMap = BeanUtil.aggByKeyToList("objId", permissions);

        userInfoDTOS.forEach(userInfoDTO -> {
            // 设置用户课程方向权限
            List<Permission> permissionList = userPermissionMap.get(userInfoDTO.getId());
            if (CollectionUtils.isNotEmpty(permissionList)) {
                userInfoDTO.setCourseDirectionHideIds(
                        permissionList.stream().map(Permission::getStatus).collect(Collectors.toList()));
            }

            if (StringUtils.isNotBlank(userInfoDTO.getIcon())) {
                userInfoDTO.setIconPath(LocalResourcesEnum.SYSTEM_FILE.getMappingUrl(userInfoDTO.getIcon()));
            }
            RoleEnum dbRoleEnum = RoleEnum.getByCode(userInfoDTO.getRole());
            if (dbRoleEnum != null) {
                userInfoDTO.setRoleName(dbRoleEnum.getRoleName());
                if ((dbRoleEnum == RoleEnum.SUPER_ADMIN
                        || dbRoleEnum == RoleEnum.INTERNET_ADMIN)
                        && !Objects.equals(userInfoDTO.getId(), currentUserId)) {
                    userInfoDTO.setAllowedModified(false);
                }
            }
            SexEnum sexEnum = SexEnum.getByCode(userInfoDTO.getSex());
            if (sexEnum != null) {
                userInfoDTO.setSexName(sexEnum.getMessage());
            }
            UserStatusEnum userStatusEnum = UserStatusEnum.getByCode(userInfoDTO.getStatus());
            if (userStatusEnum != null) {
                userInfoDTO.setStatusName(UserStatusEnum.getByCode(userInfoDTO.getStatus()).getMessage());
            }
            if (userStatusEnum != UserStatusEnum.NOT_DELETE) {
                userInfoDTO.setAllowedModified(false);
            }
        });
        return userInfoDTOS;
    }

    /**
     * 检查参数并转换参数
     *
     * @param roleEnum 用户查询的角色枚举
     * @return
     */
    private List<Integer> checkAndConvertParam(RoleEnum roleEnum, IdentityEnum identityEnum) {

        // 获取当前登录人的角色
        RoleEnum currentUserRoleEnum = RoleEnum.getByCode(userInfoHolder.getUser().getRole());

        List<Integer> roles = Lists.newArrayList();

        switch (currentUserRoleEnum) {
            case INTERNET_ADMIN:
                roles = identityEnum.getRoles();
                if (roleEnum == null) {
                    return roles;
                }
                if (!roles.contains(roleEnum.getRoleCode())) {
                    throw new BadRequestException("暂无权限查询当前角色");
                }
                return Lists.newArrayList(roleEnum.getRoleCode());
            case ADMIN:
            case SUPER_ADMIN:
                roles = identityEnum.getReleaseVersionRoles();
                if (roleEnum == null) {
                    return roles;
                }
                if (!roles.contains(roleEnum.getRoleCode())) {
                    throw new BadRequestException("暂无权限查询当前角色");
                }
                return Lists.newArrayList(roleEnum.getRoleCode());
        }

        return roles;

    }

    private User convertUser(Long userId, String password) {
        User user = new User();
        user.setId(userId);
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        return user;
    }

    private void checkUserPassword(Long userId, String oldPassword, String newPassword) {

        // 检查密码参数
        if (!ReUtil.isMatch(UserConstant.REGEX_PASSWORD, newPassword)) {
            throw new GlobalException("密码不在6-14位数字或英文范围内，请重新输入");
        }

        // 获取数据库用户信息
        UserInfoDTO userInfoDTO = getUserInfo(userId, UserStatusEnum.NOT_DELETE);

        // 被修改用户的角色
        RoleEnum saveUserRoleEnum = RoleEnum.getByCode(userInfoDTO.getRole());

        // 被修改的用户是超管、网管 并 修改人不是本人，则报无权限操作
        if ((saveUserRoleEnum == RoleEnum.SUPER_ADMIN
                || saveUserRoleEnum == RoleEnum.INTERNET_ADMIN)
                && !Objects.equals(userInfoHolder.getUserId(), userId)) {
            throw new BadRequestException("无权限修改密码");
        }

        if (StringUtils.isBlank(oldPassword)) return;

        // 将传输的密码进行加密 进行比较
        if (!new BCryptPasswordEncoder().matches(oldPassword, userInfoDTO.getPassword())) {
            throw new BadRequestException("原密码输入错误");
        }

    }

    private User checkAndConvertUser(Long userId, UpdateUserInfoParam param) {
        // 验证参数
        validUpdateUserInfoParam(param);

        // 验证逻辑，获取用户信息，其实就是想检查用户是否存在
        getUserInfo(userId, UserStatusEnum.NOT_DELETE);

        // 转换信息
        User user = BeanUtil.transform(User.class, param);
        user.setId(userId);
        user.setSex(SexEnum.getCodeByMessage(param.getSexName()));
        if (StringUtils.isBlank(user.getEmail()) && param.getShowEmail()) {
            user.setShowEmail(false);
        }
        return user;
    }

    private void validUpdateUserInfoParam(UpdateUserInfoParam param) {
        // 检查基本参数
        CreateUserParam createUserParam = BeanUtil.transform(CreateUserParam.class, param);
        validateParam(createUserParam, userInfoHolder.isStudent() ? "学号" : "工号");
    }

    private List<UserInfoDTO> convertUserInfoDTOS(List<User> users) {
        List<UserInfoDTO> userInfoDTOS = BeanUtil.batchTransform(UserInfoDTO.class, users);
        userInfoDTOS.forEach(userInfoDTO -> {
            userInfoDTO.setSexName(SexEnum.getMessageByCode(userInfoDTO.getSex()));
            userInfoDTO.setIconPath(LocalResourcesEnum.SYSTEM_FILE.getMappingUrl(userInfoDTO.getIcon()));
            userInfoDTO.setRoleName(RoleEnum.getByCode(userInfoDTO.getRole()).getRoleName());
            userInfoDTO.setRoleCode(RoleEnum.getByCode(userInfoDTO.getRole()).name());
        });

        return userInfoDTOS;
    }

    private List<CreateUserParam> checkAndConvertCreateUserParam(
            List<CreateUserParam> params, IdentityEnum identityEnum, List<Long> courseIds, Long classId, Boolean errorFlag) {

        // 过滤数据为空的
        if (CollectionUtils.isEmpty(params)) {
            throw new NotFoundException("暂无数据");
        }

        // 检查性别并获取最终的性别
        Map<String, Integer> sexMap = checkAndGetSex(params);

        RoleEnum roleEnum = RoleEnum.getByCode(userInfoHolder.getUser().getRole());
        String numberName = userInfoHolder.isTeacher() ? "学号" : "工号";

        // 检查各个参数
        params.forEach(param -> {
            // 基本验证
            if (StringUtils.isBlank(param.getName())) {
                throw new BadRequestException("姓名为必填项");
            }
            if (StringUtils.isBlank(param.getUserNumber())) {
                throw new BadRequestException(numberName + "为必填项");
            }

            if ((roleEnum == RoleEnum.INTERNET_ADMIN
                    || (roleEnum == RoleEnum.SUPER_ADMIN && identityEnum == IdentityEnum.ADMIN))
                    && StringUtils.isBlank(param.getRoleName()) && identityEnum != IdentityEnum.STUDENT) {
                throw new BadRequestException("角色为必填项");
            }
            validateParam(param, numberName);

            // 设置性别
            if (StringUtils.isNotBlank(param.getSexName())) {
                param.setSex(sexMap.get(param.getSexName()));
            }

        });
        if ((roleEnum == RoleEnum.INTERNET_ADMIN
                || roleEnum == RoleEnum.SUPER_ADMIN || roleEnum == RoleEnum.ADMIN) && identityEnum == IdentityEnum.STUDENT) {
            // 获取全部角色并转换为Map集合
            Map<String, Integer> roleMap = Arrays.stream(RoleEnum.values())
                    .collect(Collectors.toMap(RoleEnum::getRoleName, RoleEnum::getRoleCode));

            // 设置角色
            params.forEach(param -> {
                if (StringUtils.isEmpty(param.getRoleName())) {
                    param.setRole(identityEnum.getReleaseVersionRoles().get(0));
                    return;
                }
                if (roleMap.get(param.getRoleName()) == null) {
                    throw new BadRequestException(param.getRoleName() + "角色不存在");
                }
                param.setRole(roleMap.get(param.getRoleName()));
            });
        } else if (userInfoHolder.isTeacher() && identityEnum == IdentityEnum.TEACHER) {
            // 获取全部角色并转换为Map集合
            Map<String, Integer> roleMap = Arrays.stream(RoleEnum.values())
                    .collect(Collectors.toMap(RoleEnum::getRoleName, RoleEnum::getRoleCode));

            // 设置角色
            params.forEach(param -> {
                if (StringUtils.isEmpty(param.getRoleName())) {
                    param.setRole(identityEnum.getReleaseVersionRoles().get(0));
                    return;
                }
                if (roleMap.get(param.getRoleName()) == null) {
                    throw new BadRequestException(param.getRoleName() + "角色不存在");
                }
                param.setRole(roleMap.get(param.getRoleName()));
            });
        } else {
            // 检查角色并设置最终的角色
            checkAndSetRole(params, identityEnum);
        }

        // 将页面工号重复进行过滤
        Map<String, Long> userNumberMap = params.stream()
                .collect(Collectors.groupingBy(CreateUserParam::getUserNumber, Collectors.counting()))
                .entrySet().stream()
                .filter(map -> map.getValue() > 1).collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
        if (MapUtils.isNotEmpty(userNumberMap)) {
            throw new BadRequestException(StringUtils.join(userNumberMap.keySet(), ",") + numberName + "重复");
        }


        // 查询数据库的工号与用户填写的工号是否相同 并 过滤条件
        return checkAndFilterUserNumberIsExist(params, courseIds, classId, errorFlag, identityEnum);

    }

    private void validateParam(CreateUserParam param, String str) {
        if (param == null) {
            throw new BadRequestException();
        }
        String content = StringUtils.isEmpty(param.getUserNumber()) ? "" : "'" + param.getUserNumber() + "'" + str + ",";
        if (StringUtils.isNotBlank(param.getName()) && param.getName().length() > 10) {
            throw new BadRequestException(content + "姓名已超出10个字符，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getUserNumber()) && param.getUserNumber().length() > 20) {
            throw new BadRequestException(content + str + "已超出20个字符，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getTelephoneNumber())
                && (param.getTelephoneNumber().length() != 11
                || !ReUtil.isMatch(UserConstant.REGEX_NUMBER, param.getTelephoneNumber()))) {
            throw new BadRequestException(content + "手机号不符合11位正确格式，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getEmail())
                && (param.getEmail().length() > 50
                || !ReUtil.isMatch(UserConstant.REGEX_EMAIL, param.getEmail()))) {

            throw new BadRequestException(content + "邮箱不符合正确格式，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getProvince()) && param.getProvince().length() > 10) {
            throw new BadRequestException(content + "省份已超出10个字符，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getSchoolName()) && param.getSchoolName().length() > 30) {
            throw new BadRequestException(content + "学校已超出30个字符，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getApplicant()) && param.getApplicant().length() > 20) {
            throw new BadRequestException(content + "申请人已超出20个字符，请重新输入");
        }
        if (StringUtils.isNotBlank(param.getPassword())
                && !ReUtil.isMatch(UserConstant.REGEX_PASSWORD, param.getPassword())) {
            throw new BadRequestException(content + "密码不在6-14位数字或英文范围内，请重新输入");
        }

        try {
            // 设置销毁时间
            param.setDestroyTime(getDestroyTime(param.getDestroyTimeStr()));
        } catch (Exception e) {
            throw new BadRequestException(content + e.getMessage());
        }
    }

    private List<CreateUserParam> checkAndFilterUserNumberIsExist(List<CreateUserParam> params,
                                                                  List<Long> courseIds, Long classId, Boolean errorFlag, IdentityEnum identityEnum) {

        // 获取学号或工号
        List<String> userNumberList = params.stream().map(CreateUserParam::getUserNumber).collect(Collectors.toList());
        //学号或工号当前还是学生
        if (userInfoHolder.isAdmin() && identityEnum.name().equals("STUDENT")) {
            List<String> userNumbers = params.stream().map(CreateUserParam::getUserNumber).collect(Collectors.toList());
            return querycheckAndFilterUserNumberNa(params, userNumbers, classId, errorFlag);
        }
        // 如果是教师，判断学生同课程下学号重复问题
        if (userInfoHolder.isTeacher()) {
            return checkAndFilterUserNumber(params, courseIds, classId, errorFlag);
        }
        // 判断工号是否重复
        UserExample example = new UserExample();
        example.createCriteria()
                .andUserNumberIn(userNumberList)
                .andStatusNotEqualTo(UserStatusEnum.DELETED.getCode());
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(users)) {
            String exceptionContent = users.stream()
                    .map(User::getUserNumber)
                    .limit(3)
                    .collect(Collectors.joining(","));
            String number = userInfoHolder.isTeacher() ? "学号" : "工号";
            throw new GlobalException(exceptionContent + number + "已存在");
        }

        return params;
    }

    private List<CreateUserParam> querycheckAndFilterUserNumberNa(List<CreateUserParam> params, List<String> userNumber, Long classid, Boolean errorFlag) {
        List<UserInfoDTO> users = userMapperExt.selectByExampleNa(userNumber);
        StringBuilder names = new StringBuilder();
        if (CollectionUtils.isNotEmpty(users)) {
            for (int i = 0; i < users.size(); i++) {
                if (i >= 3) {
                    names.append("...等");
                    break;
                }
                if (i > 0) {
                    names.append(",");
                }
                names.append(users.get(i).getName());

            }
            throw new GlobalException(StringUtils.join("系统中已存在", names, "学生"));
        }
        querycheckAndFilterUserNumber(params, userNumber);
        List<CreateUserParam> result3 = Lists.newArrayList();

        for (CreateUserParam createUserParam : params) {
            if (createUserParam.getId() != null) {
                result3.add(createUserParam);
            }
        }
        Map<Long, String> collect = result3.stream().collect(Collectors.toMap(CreateUserParam::getId, CreateUserParam::getUserNumber));
        List<Long> listuserids = result3.stream().map(CreateUserParam -> Long.valueOf(CreateUserParam.getId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(listuserids)) return params;
        if (errorFlag == null) {

            List result = Lists.newArrayList();
            List<ClassCourseDTO> result2 = Lists.newArrayList();

            listuserids.forEach(userid -> {
                        List<Class> classes = listClassIdByStudentIds(Lists.newArrayList(userid));
                        List<Long> listclass = classes.stream().map(Class::getId).collect(Collectors.toList());
                        List<ClassCourseDTO> classCourseDTOS = classService.queryClassCourse(listclass);

                        classCourseDTOS.stream().forEach(ClassCourseDTO -> {
                            CourseBasicDTO course = courseService.getCourse(ClassCourseDTO.getCourseId());
                            List<ClassCourseDTO> classCourseDTOS1 = classService.queryClassCourse(Lists.newArrayList(classid));
                            classCourseDTOS1.stream().forEach(ClassCourseDTO1 -> {
                                CourseBasicDTO course1 = courseService.getCourse(ClassCourseDTO1.getCourseId());
                                if (course1.getCourseBasicId() == course.getCourseBasicId()) {
                                    result2.add(ClassCourseDTO1);
                                    result2.add(ClassCourseDTO);
                                }
                            });

                        });
                        if (CollectionUtils.isNotEmpty(result2)) {
                            result2.stream().forEach(item -> {
                                if (!item.getId().equals(classid)) {
                                    result.add(StringUtils.join(collect.get(userid), "学生已经在教师教授的虚拟班级‘", item.getName(),
                                            "’", "中。"));
                                }
                            });
                            result2.clear();
                        }

                    }
            );
            if (result != null && result.size() > 0) {
                throw new ClassUserException(ResultEnum.USER_EXIST, result);
            }
            return params;
        }

        if (errorFlag) {
            // 删除其他数据
            // 哪些用户是存在有班级的
            List<Class> classes1 = listClassIdByStudentIds(listuserids);
            if (CollectionUtils.isEmpty(classes1)) return params;
            List<Long> listclass1 = classes1.stream().map(Class::getId).collect(Collectors.toList());
            List<ClassCourseDTO> classCourseDTOS1 = classService.queryClassCourse(listclass1);
            if (CollectionUtils.isEmpty(classCourseDTOS1)) return params;

            List<UserClassInfoDTO> userClassDTOS = userClassMapperExt.queryUserClassInfo(
                    Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode(), UserStatusEnum.ACCOUNT_CANCELLATION.getCode()),
                    userNumber, RoleEnum.STUDENT.getRoleCode()
            );
            if (CollectionUtils.isEmpty(userClassDTOS)) return params;
            Map<Long, List<UserClassInfoDTO>> classIdUserMap = BeanUtil.aggByKeyToList("id", userClassDTOS);

            // 根据班级id集合获取未删除的课程信息
            List<ClassCourseDTO> classCourses = classService.queryClassCourse(Lists.newArrayList(classIdUserMap.keySet()));
            if (CollectionUtils.isEmpty(classCourses)) return params;

            Map<Long, ClassCourseDTO> classCourseMap = BeanUtil.mapByKey("id", classCourseDTOS1);
            classIdUserMap.forEach((dbClassId, userClassInfoDTOS) -> {

                List<Long> studentIds = userClassInfoDTOS.stream()
                        .map(UserClassInfoDTO::getUserId).collect(Collectors.toList());

                if (CollectionUtils.isEmpty(studentIds)) return;

                ClassCourseDTO classCourse = classCourseMap.get(dbClassId);
                if (classCourse == null) return;

                List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                        Lists.newArrayList(classCourse.getCourseId()), null, null, null);

                List<Long> chapterIds = chapters.stream().map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());
                List<Long> experimentChapterIds = ChapterEnum.TASK.getConvertData(chapters).stream()
                        .map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());

                // 删除原来的班级关联关系表
                userService.batchDeleteUserClass(Lists.newArrayList(dbClassId), studentIds, true);

                List<String> notesPaths = null;

                if (CollectionUtils.isNotEmpty(chapterIds)) {

                    List<Long> userClassIds = userClassInfoDTOS.stream()
                            .map(UserClassInfoDTO::getUserClassId).collect(Collectors.toList());

                    // 删除实验报告
                    experimentService.deleteByStudentIdsChapterIds(userClassIds, chapterIds);

                    // 删除随堂练习答题情况
                    practiceService.deletePractice(userClassIds, chapterIds);

                    // 删除笔记，并获取笔记静态资源
                    notesPaths = chapterService.deleteNotes(chapterIds, studentIds, null);

                    // 章节记录
                    operationService.batchDeleteOperation(chapterIds, studentIds, EventCodeEnum.CHAPTER_RECORDING);
                    operationService.batchDeleteOperation(chapterIds, studentIds, EventCodeEnum.CHAPTER_STUDIED);

                }

                // 删除虚机
                if (CollectionUtils.isNotEmpty(experimentChapterIds)) {
                    containerService.deleteContainerByContext(ContextTypeEnum.TASK.getCode(), experimentChapterIds, studentIds);
                }

                asyncTask.asyncDeleteStaticResources(notesPaths);

            });

        }

        return params;
    }

    private List<CreateUserParam> querycheckAndFilterUserNumber(List<CreateUserParam> params, List<String> userNumbers) {
        // 设置params的userid
        UserExample example = new UserExample();
        example.createCriteria().andUserNumberIn(userNumbers).andStatusNotEqualTo(UserStatusEnum.DELETED.getCode());
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(users)) {
            List<String> userNumberList = users.stream()
                    .filter(user -> RoleEnum.STUDENT != RoleEnum.getByCode(user.getRole())
                            || (RoleEnum.STUDENT == RoleEnum.getByCode(user.getRole())
                            && UserStatusEnum.ACCOUNT_CANCELLATION == UserStatusEnum.getByCode(user.getStatus())))
                    .map(User::getUserNumber).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(userNumberList)) {
                throw new GlobalException(
                        StringUtils.join("系统中已存在",
                                userNumberList.stream().limit(5).collect(Collectors.joining("，")),
                                "账号"));
            }
            Map<Long, User> userNumberMap = BeanUtil.mapByKey("userNumber", users);
            params.forEach(param -> {
                User user = userNumberMap.get(param.getUserNumber());
                if (user != null) {
                    param.setId(user.getId());
                }
            });
        }
        return params;
    }

    public List<CreateUserParam> checkAndFilterUserNumber(List<CreateUserParam> params,
                                                          List<Long> courseIds, Long classId, Boolean errorFlag) {
        List<String> userNumbers = params.stream().map(CreateUserParam::getUserNumber).collect(Collectors.toList());

        querycheckAndFilterUserNumber(params, userNumbers);
        // 哪些用户是存在有班级的
        List<UserClassInfoDTO> userClassDTOS = userClassMapperExt.queryUserClassInfo(
                Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode(), UserStatusEnum.ACCOUNT_CANCELLATION.getCode()),
                userNumbers, RoleEnum.STUDENT.getRoleCode()
        );
        if (CollectionUtils.isEmpty(userClassDTOS)) return params;
        Map<Long, List<UserClassInfoDTO>> classIdUserMap = BeanUtil.aggByKeyToList("id", userClassDTOS);

        // 根据班级id集合获取未删除的课程信息
        List<ClassCourseDTO> classCourses = classService.queryClassCourse(Lists.newArrayList(classIdUserMap.keySet()));
        if (CollectionUtils.isEmpty(classCourses)) return params;

        // 根据课程id，获取所有教师需要引用这门课程的信息
        List<Course> courses = courseService.queryCourses(courseIds);
        if (CollectionUtils.isEmpty(classCourses)) {
            throw new BadRequestException("该课程不存在");
        }
        List<Long> dbCourseIds = courses.stream().map(Course::getId).collect(Collectors.toList());

        classCourses = classCourses.stream()
                .filter(classCourse -> dbCourseIds.contains(classCourse.getCourseId()))
                .collect(Collectors.toList());

        List<Long> classIds = classCourses.stream().map(ClassCourseDTO::getId).collect(Collectors.toList());

        classIdUserMap = classIdUserMap.entrySet().stream()
                .filter(map -> classIds.contains(map.getKey()))
                .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

        if (MapUtils.isEmpty(classIdUserMap)) return params;

        // 获取班级信息
        List<Long> classIdList = Lists.newArrayList(classIdUserMap.keySet());
        List<Class> classes = classService.queryClassByIds(classIdList);
        Map<Long, Class> classMap = BeanUtil.mapByKey("id", classes);

        // 课程是否考试
        List<com.xlh.dto.courseTest.CourseClassDTO> list = Lists.newArrayList();
        classCourses.forEach(classCourseDTO -> {
            list.add(new com.xlh.dto.courseTest.CourseClassDTO(classCourseDTO.getCourseId(), classCourseDTO.getId()));
        });
        List<com.xlh.dto.courseTest.CourseClassDTO> testingData = paperService.getCourseClassPaper(list);

        // 如果考试获取考试的班级id集合
        List<Long> testingClassIds = null;
        if (CollectionUtils.isNotEmpty(testingData)) {
            testingClassIds = testingData.stream()
                    .map(com.xlh.dto.courseTest.CourseClassDTO::getClassId).distinct().collect(Collectors.toList());
        }

        if (errorFlag == null) {
            List<String> result = Lists.newArrayList();
            List<Long> finalTestingClassIds = testingClassIds;
            classIdUserMap.forEach((dbClassId, userClassInfoDTOS) -> {

                List<String> userNames = userClassInfoDTOS.stream()
                        .map(UserClassInfoDTO::getUserName).collect(Collectors.toList());
                String userNameStr = StringUtils.join(userNames.stream()
                        .limit(3).collect(Collectors.joining("，")), userNames.size() > 3 ? "等" : "");
                if (Objects.equals(classId, dbClassId)) {
                    throw new GlobalException(StringUtils.join(userNameStr, "已存在当前班级，不能重复添加"));
                }

                Class classInfo = classMap.get(dbClassId);
                if (classInfo != null && classInfo.getUserId() == null) {
                    throw new GlobalException(
                            StringUtils.join(userNameStr, "已存在'",
                                    classInfo.getName(), "'班级中，不能重复添加"));
                }

                UserClassInfoDTO userClassInfoDTO = userClassInfoDTOS.get(0);

                result.add(StringUtils.join(userNameStr, "学生已经在‘", userClassInfoDTO.getName(),
                        "’班级（", userClassInfoDTO.getId(), "编号）中存在",
                        CollectionUtils.isNotEmpty(finalTestingClassIds) && finalTestingClassIds.contains(dbClassId) ?
                                "并处于考试中" : ""));
            });
            throw new ClassUserException(ResultEnum.USER_EXIST, result);
        }
        if (errorFlag) {

            /**
             * 1. 删除实验报告
             * 2. 删除随堂练习答题情况
             * 3. 删除虚机
             * 4. 删除笔记(学习课件笔记、实验笔记)
             * 5. 学生是否已学过某章节（我的课程 - 详情 - 已学过的章节打对勾）
             * 6. 删除原来的用户班级关联关系
             */

            // 删除其他数据
            Map<Long, ClassCourseDTO> classCourseMap = BeanUtil.mapByKey("id", classCourses);
            classIdUserMap.forEach((dbClassId, userClassInfoDTOS) -> {

                List<Long> studentIds = userClassInfoDTOS.stream()
                        .map(UserClassInfoDTO::getUserId).collect(Collectors.toList());

                if (CollectionUtils.isEmpty(studentIds)) return;

                ClassCourseDTO classCourse = classCourseMap.get(dbClassId);
                if (classCourse == null) return;

                List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                        Lists.newArrayList(classCourse.getCourseId()), null, null, null);

                List<Long> chapterIds = chapters.stream().map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());
                List<Long> experimentChapterIds = ChapterEnum.TASK.getConvertData(chapters).stream()
                        .map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());

                // 删除原来的班级关联关系表
                userService.batchDeleteUserClass(Lists.newArrayList(dbClassId), studentIds, true);

                List<String> notesPaths = null;

                if (CollectionUtils.isNotEmpty(chapterIds)) {

                    List<Long> userClassIds = userClassInfoDTOS.stream()
                            .map(UserClassInfoDTO::getUserClassId).collect(Collectors.toList());

                    // 删除实验报告
                    experimentService.deleteByStudentIdsChapterIds(userClassIds, chapterIds);

                    // 删除随堂练习答题情况
                    practiceService.deletePractice(userClassIds, chapterIds);

                    // 删除笔记，并获取笔记静态资源
                    notesPaths = chapterService.deleteNotes(chapterIds, studentIds, null);

                    // 章节记录
                    operationService.batchDeleteOperation(chapterIds, studentIds, EventCodeEnum.CHAPTER_RECORDING);
                    operationService.batchDeleteOperation(chapterIds, studentIds, EventCodeEnum.CHAPTER_STUDIED);

                }

                // 删除虚机
                if (CollectionUtils.isNotEmpty(experimentChapterIds)) {
                    containerService.deleteContainerByContext(ContextTypeEnum.TASK.getCode(), experimentChapterIds, studentIds);
                }

                asyncTask.asyncDeleteStaticResources(notesPaths);

            });

            return params;
        }

        // 将数据库已经存在的数据进行过滤
        for (Map.Entry<Long, List<UserClassInfoDTO>> entry : classIdUserMap.entrySet()) {
            params = params.stream().filter(param ->
                    !entry.getValue().stream()
                            .map(UserClassInfoDTO::getUserNumber)
                            .collect(Collectors.toList())
                            .contains(param.getUserNumber())
            ).collect(Collectors.toList());
        }

        return params;
    }

    private Map<String, Integer> checkAndGetSex(List<CreateUserParam> params) {
        // 获取全部角色并转换为Map集合
        Map<String, Integer> sexEnum = Arrays.stream(SexEnum.values())
                .collect(Collectors.toMap(SexEnum::getMessage, SexEnum::getCode));

        // 将角色参数进行
        params.forEach(param -> {
            if (StringUtils.isNotBlank(param.getSexName()) && sexEnum.get(param.getSexName()) == null) {
                throw new BadRequestException(param.getSexName() + "性别不存在");
            }
        });
        return sexEnum;
    }

    private void checkAndSetRole(List<CreateUserParam> params, IdentityEnum identityEnum) {
        // 获取全部角色并转换为Map集合
        Map<String, Integer> roleMap = Arrays.stream(RoleEnum.values())
                .collect(Collectors.toMap(RoleEnum::getRoleName, RoleEnum::getRoleCode));

        // 设置角色
        params.forEach(param -> {
            if (StringUtils.isEmpty(param.getRoleName())) {
                param.setRole(identityEnum.getReleaseVersionRoles().get(0));
                return;
            }
            if (roleMap.get(param.getRoleName()) == null) {
                throw new BadRequestException(param.getRoleName() + "角色不存在");
            }
            param.setRole(roleMap.get(param.getRoleName()));
        });

        // 检查权限及角色
        checkPermission(params.stream().map(CreateUserParam::getRole).collect(Collectors.toList()));

    }

    private User checkAndSetGetUpdateUserParam(Long userId, UserParam param, IdentityEnum identityEnum) {

        // 检查参数
        CreateUserParam transform = BeanUtil.transform(CreateUserParam.class, param);
        validateParam(transform, identityEnum == IdentityEnum.TEACHER
                || identityEnum == IdentityEnum.ADMIN ? "工号" : "学号");

        // 设置销毁时间
        param.setDestroyTime(transform.getDestroyTime());

        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null || UserStatusEnum.NOT_DELETE != UserStatusEnum.getByCode(user.getStatus())) {
            throw new NotFoundException("当前用户不存在或无权限修改");
        }

        RoleEnum roleEnum = RoleEnum.getByCode(user.getRole());
        if (roleEnum == RoleEnum.INTERNET_ADMIN || roleEnum == RoleEnum.SUPER_ADMIN) {
            throw new NotFoundException("暂无权限修改用户信息");
        }

        if (StringUtils.isNotEmpty(param.getRoleName())
                && RoleEnum.getByName(param.getRoleName()) == null) {
            throw new BadRequestException(param.getRoleName() + "角色不存在");
        }
        // 角色判断
        if (StringUtils.isNotBlank(param.getRoleName())) {
            checkPermission(Lists.newArrayList(RoleEnum.getCodeByName(param.getRoleName())));
            // 设置角色
            param.setRole(RoleEnum.getCodeByName(param.getRoleName()));
        }

        // 性别
        if (StringUtils.isNotBlank(param.getSexName())) {
            param.setSex(SexEnum.getCodeByMessage(param.getSexName()));
        }

        return user;
    }

    private void checkPermission(List<Integer> roles) {
        // 互联网管理员不允许添加/编辑、普管不允许选择角色
        RoleEnum currentRoleEnum = RoleEnum.getByCode(userInfoHolder.getUser().getRole());
        roles.forEach(role -> {
            RoleEnum roleEnum = RoleEnum.getByCode(role);
            if (roleEnum == RoleEnum.INTERNET_ADMIN
                    || currentRoleEnum == RoleEnum.STUDENT
                    || (currentRoleEnum == RoleEnum.MARKET_TEACHER && roleEnum != RoleEnum.STUDENT)
                    || (currentRoleEnum == RoleEnum.UNIVERSITY_TEACHER && roleEnum != RoleEnum.STUDENT)
                    || (currentRoleEnum == RoleEnum.TEACHER && roleEnum != RoleEnum.STUDENT)
                    || (currentRoleEnum == RoleEnum.ADMIN && roleEnum != RoleEnum.TEACHER)
                    || (currentRoleEnum == RoleEnum.SUPER_ADMIN
                    && roleEnum != RoleEnum.TEACHER
                    && roleEnum != RoleEnum.ADMIN
                    && roleEnum != RoleEnum.SUPER_ADMIN)) {
                throw new BadRequestException("暂无权限添加或修改" + roleEnum.getRoleName());
            }
        });
    }

    /**
     * 设置工号/学号
     *
     * @return
     */
    private String setUserNumber(int i) {

        // 获取今天当前的日期（yyyyMMdd）
        String date = DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);

        // 获取user表中以日期为前缀的学号
        UserExample example = new UserExample();
        example.createCriteria().andUserNumberLike(date + "%");
        List<User> users = userMapper.selectByExample(example);

        // 获取学号的最大值
        Integer maxNum = users.stream()
                .filter(user -> NumberUtil.isInteger(user.getUserNumber()))
                .map(user -> {
                    String value = user.getUserNumber().replace(date, "");
                    return Integer.valueOf(StringUtils.isEmpty(value) ? "0" : value);
                }).reduce(Integer::max).orElse(0);

        // 返回相应的值
        return StringUtils.join(date, String.format("%02d", maxNum + i));
    }

    /**
     * 检查申请码是否正确
     *
     * @param invitationCode 申请码
     */
    private void checkInvitationCode(String invitationCode) {

        List<SystemConfig> systemConfigs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.INVITATION_CODE.getKey()));

        if (CollectionUtils.isEmpty(systemConfigs)) {
            throw new BadRequestException("申请码错误");
        }
        String dbInvitaionCode = systemConfigs.stream().findFirst().get().getKeyValue();
        if (!Objects.equals(dbInvitaionCode, invitationCode)) {
            throw new BadRequestException("申请码不匹配");
        }

    }

    private List<UserInfoDTO> filterDeletedUserIds(List<Long> userIds) {

        // 获取当前用户id及角色
        Long currentUserId = userInfoHolder.getUserId();
        RoleEnum currentRoleEnum = RoleEnum.getByCode(userInfoHolder.getUser().getRole());

        // 获取需要被删除的用户信息
        List<UserInfoDTO> users = queryUserInfos(userIds,
                Lists.newArrayList(UserStatusEnum.NOT_DELETE, UserStatusEnum.ACCOUNT_CANCELLATION));
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }

        // 将数据库的id进行转换
        List<Long> dbUserIds = users.stream().map(UserInfoDTO::getId).collect(Collectors.toList());
        if (userInfoHolder.isTeacher() && users.get(0).getRole() == 1) {
            List<Long> removeUserIs = users.stream()
                    .filter(user -> currentRoleEnum == RoleEnum.getByCode(user.getRole())
                            && user.getRole() != 1 && !Objects.equals(user.getId(), currentUserId))
                    .map(UserInfoDTO::getId).collect(Collectors.toList());
            dbUserIds.removeAll(removeUserIs);
        } else {
            // 获取登录人与被删除的人是同级别的角色，但不是本人
            List<Long> removeUserIs = users.stream()
                    .filter(user -> currentRoleEnum == RoleEnum.getByCode(user.getRole())
                            && !Objects.equals(user.getId(), currentUserId))
                    .map(UserInfoDTO::getId).collect(Collectors.toList());
            dbUserIds.removeAll(removeUserIs);
        }
        if (CollectionUtils.isEmpty(dbUserIds)) {
            return null;
        }

        return users.stream()
                .filter(userInfoDTO -> dbUserIds.contains(userInfoDTO.getId())).collect(Collectors.toList());

    }

    private Date getDestroyTime(String timeStr) {
        Date paramDate = null;
        if (StringUtils.isNotBlank(timeStr)) {
            try {
                paramDate = DateUtil.beginOfDay(DateUtil.parse(timeStr, "yyyy/M/d"));
            } catch (DateException e) {
                throw new BadRequestException("销毁时间不符合'yyyy/M/d'格式，请重新输入");
            }
        }
        if (paramDate != null) {
            Date currentDate = DateUtil.beginOfDay(DateUtil.date());
            if (paramDate.getTime() <= currentDate.getTime()) {
                throw new BadRequestException("销毁时间不能早于当前日期，请重新输入");
            }
        }
        return paramDate;
    }

    private List<User> checkUpdateUserStatusParam(List<Long> userIds, UpdateUserStatusParam param) {

        UserStatusEnum updateUserStatusEnum = UserStatusEnum.getByCode(param.getStatus());
        if (updateUserStatusEnum == null || updateUserStatusEnum == UserStatusEnum.DELETED)
            throw new BadRequestException();

        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdIn(userIds);
        List<User> users = userMapper.selectByExample(userExample);
        if (CollectionUtils.isEmpty(users)) throw new BadRequestException();

        users.forEach(user -> {
            UserStatusEnum dbUserStatusEnum = UserStatusEnum.getByCode(user.getStatus());
            if (dbUserStatusEnum == UserStatusEnum.DELETED) throw new BadRequestException();
            if (dbUserStatusEnum == updateUserStatusEnum) throw new BadRequestException();
        });

        return users;

    }

    private List<UserClass> getUserClass(List<Long> classIds) {
        UserClassExample example = new UserClassExample();
        example.createCriteria().andClassIdIn(classIds).andDeletedEqualTo(false);
        return userClassMapper.selectByExample(example);
    }

    /**
     * 获取班级信息关联user表
     *
     * @param classIds
     * @return
     */
    private List<UserClass> getUserClassLeftUser(List<Long> classIds) {

        List<UserClass> userClasses = userMapperExt.findByClassIds(classIds);

        return userClasses;
    }


    private void deleteUser(List<Long> userIds, Boolean logicDeleted) {

        if (CollectionUtils.isEmpty(userIds)) return;

        if (logicDeleted) {
            userMapperExt.batchDeleteUser(userIds, UserStatusEnum.DELETED.getCode());
            return;
        }
        UserExample example = new UserExample();
        example.createCriteria().andIdIn(userIds);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) return;

        userMapper.deleteByExample(example);

        // 删除用户额外表
        List<Long> userExtendIds = users.stream().filter(user -> user.getUserExtendId() != null)
                .map(User::getUserExtendId)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(userExtendIds)) return;
        UserExtendExample userExtendExample = new UserExtendExample();
        userExtendExample.createCriteria().andIdIn(userExtendIds);
        userExtendMapper.deleteByExample(userExtendExample);
    }

    private void checkErrorFlagParam(List<Long> teacherIds, List<Long> studentUserIds,
                                     Boolean errorFlag, List<CourseDTO> courseDTOS, Long courseId) {

        /**
         * 检查：
         * 1. 教师下有学生
         * 2. 教师正在给学生考试
         * 3. 教师含有创作的课程
         * 4. 教师创作的课程是否被其他教师占用
         */

        if (errorFlag != null
                || (CollectionUtils.isEmpty(teacherIds) && CollectionUtils.isEmpty(studentUserIds))) return;

        if (CollectionUtils.isNotEmpty(teacherIds) && CollectionUtils.isNotEmpty(courseDTOS)) {
            List<String> resultMessages = Lists.newArrayList("当前教师含有课程");
            try {
                courseService.checkDeleteParamAndGet(
                        courseDTOS.stream().map(CourseDTO::getId).collect(Collectors.toList()), errorFlag);
            } catch (Exception e) {
                resultMessages.add(e.getMessage());
            }
            throw new DeleteDealOperatingException(StringUtils.join(resultMessages, ","));
        }
        if (CollectionUtils.isNotEmpty(studentUserIds) && paperAnswerSheetService.isTesting(studentUserIds, courseId)) {
            throw new DeleteDealOperatingException("学生正在考试");
        }

    }

    private void checkErrorFlagParams(List<Long> teacherIds, List<Long> studentUserIds,
                                      Boolean errorFlag, List<CourseDTO> courseDTOS, List<Long> courseId) {


        if (CollectionUtils.isNotEmpty(studentUserIds) && paperAnswerSheetService.isTestings(studentUserIds, courseId)) {
            throw new DeleteDealOperatingException("学生正在考试");
        }

    }

    private void deleteTeacherIds(List<Long> userIds, List<CourseDTO> courseDTOS, Boolean errorFlag,
                                  Boolean logicDeleted, Boolean updatePreseted) {

        if (CollectionUtils.isEmpty(userIds)) return;

        // 删除教师模板
        List<String> templates = templateService.deleteBatchTemplate(userIds);

        // 删除课程
        if (CollectionUtils.isNotEmpty(courseDTOS)) {
            courseService.deleteBatchCourse(
                    courseDTOS.stream().map(CourseDTO::getId).collect(Collectors.toList()),
                    errorFlag, logicDeleted, updatePreseted);
        }

        // 删除助教
        courseService.deleteCourseTeachers(userIds);

        // 删除教师的权限
        List<Permission> permissionList = systemConfigService.queryPermission(
                userIds, PermissionEnum.COURSE_DIRECTION_HIDE);
        systemConfigService.deletePermission(
                permissionList.stream().map(Permission::getId).collect(Collectors.toList()));

        asyncTask.asyncDeleteStaticResources(templates);

    }

    private void deleteStudentIds(List<Long> userIds, List<Long> courseIds, Long classId) {
        if (CollectionUtils.isEmpty(userIds) || CollectionUtils.isEmpty(courseIds)) return;
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                courseIds, null, null, null);

        List<Long> chapterIds = chapters.stream().map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());
        List<Long> experimentChapterIds = chapters.stream()
                .filter(infoDTO -> ChapterTypeEnum.isContainsExperiment(infoDTO.getType()))
                .map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());

        List<String> notesPaths = null;

        // 获取用户班级id
        List<UserClass> userClasses = listUserClass(classId);
        List<Long> userClassIds = null;
        if (CollectionUtils.isNotEmpty(userClasses)) {
            userClassIds = userClasses.stream()
                    .filter(userClass -> userIds.contains(userClass.getUserId()))
                    .map(UserClass::getId).collect(Collectors.toList());
        }

        if (CollectionUtils.isNotEmpty(chapterIds)) {
            // 删除笔记，并获取笔记静态资源
            notesPaths = chapterService.deleteNotes(chapterIds, userIds, null);

            // 删除章节记录
            operationService.batchDeleteOperation(chapterIds, userIds, EventCodeEnum.CHAPTER_RECORDING);
            operationService.batchDeleteOperation(chapterIds, userIds, EventCodeEnum.CHAPTER_STUDIED);

            // 删除实验报告
            experimentService.deleteByStudentIdsChapterIds(userClassIds, chapterIds);

            // 删除随堂练习答题情况
            practiceService.deletePractice(userClassIds, chapterIds);
        }

        // 删除环境实训记录
        trainingReportService.deleteTrainingReportByUserIds(userIds);

        // 删除虚机
        if (CollectionUtils.isNotEmpty(experimentChapterIds)) {
            containerService.deleteContainerByContext(ContextTypeEnum.TASK.getCode(), experimentChapterIds, userIds);
        }

        asyncTask.asyncDeleteStaticResources(notesPaths);

    }

    public void deleteStudentId(List<Long> userIds, Long courseId, Long classId) {
        if (CollectionUtils.isEmpty(userIds)) return;

        List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                Lists.newArrayList(courseId), null, null, null);
        List<Long> chapterIds = chapters.stream().map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());
        List<Long> experimentChapterIds = ChapterEnum.TASK.getConvertData(chapters).stream()
                .map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());

        // 获取用户班级id
        List<UserClass> userClasses = listUserClass(classId);
        List<Long> userClassIds = null;
        if (CollectionUtils.isNotEmpty(userClasses)) {
            userClassIds = userClasses.stream()
                    .filter(userClass -> userIds.contains(userClass.getUserId()))
                    .map(UserClass::getId).collect(Collectors.toList());
        }

        List<String> notesPaths = null;
        if (CollectionUtils.isNotEmpty(chapterIds)) {
            // 删除笔记，并获取笔记静态资源
            notesPaths = chapterService.deleteNotes(chapterIds, userIds, null);

            // 删除章节记录
            operationService.batchDeleteOperation(chapterIds, userIds, EventCodeEnum.CHAPTER_RECORDING);
            operationService.batchDeleteOperation(chapterIds, userIds, EventCodeEnum.CHAPTER_STUDIED);
        }

        if (CollectionUtils.isNotEmpty(chapterIds) && CollectionUtils.isNotEmpty(userClassIds)) {
            // 删除随堂练习答题情况
            practiceService.deletePractice(userClassIds, chapterIds);

            // 删除实验报告
            experimentService.deleteByStudentIdsChapterIds(userClassIds, chapterIds);
        }

        // 删除环境实训记录
        trainingReportService.deleteTrainingReportByUserIds(userIds);

        // 删除虚机
        if (CollectionUtils.isNotEmpty(experimentChapterIds)) {
            containerService.deleteContainerByContext(ContextTypeEnum.TASK.getCode(), experimentChapterIds, userIds);
        }

        asyncTask.asyncDeleteStaticResources(notesPaths);

    }

    private User insertUser(CreateUniversityTeacherParam param) {
        UserExtend userExtend = BeanUtil.transform(UserExtend.class, param);
        userExtend.setApplicant(StringUtils.isNotBlank(param.getApplicant()) ?
                param.getApplicant() : userInfoHolder.getUser().getName());
        if (userDestroyedDays != null) {
            param.setDestroyedDays(userDestroyedDays);
        }
        userExtend.setDestroyTime(DateUtil.offsetDay(new Date(), param.getDestroyedDays()));
        if (StringUtils.isNotBlank(param.getDestroyTimeStr())) {
            userExtend.setDestroyTime(getDestroyTime(param.getDestroyTimeStr()));
        }
        userExtendMapper.insertSelective(userExtend);

        User user = new User();
        if (StringUtils.isNotBlank(param.getUserNumber())) {
            user.setUserNumber(param.getUserNumber());
        } else {
            user.setUserNumber(setUserNumber(1));
        }

        RoleEnum roleEnum = RoleEnum.getByName(param.getRoleName());
        Integer sexCode = SexEnum.getCodeByMessage(param.getSexName());
        user.setRole(roleEnum == null ? RoleEnum.UNIVERSITY_TEACHER.getRoleCode() : roleEnum.getRoleCode());
        user.setUserExtendId(userExtend.getId());
        user.setName(StringUtils.isNotBlank(param.getName()) ? param.getName() : RandomUtil.randomEle(NAMES) + "教师");
        user.setPassword(StringUtils.isNotBlank(param.getPassword()) ? param.getPassword() : user.getUserNumber());
        user.setTelephoneNumber(param.getTelephoneNumber());
        user.setEmail(StringUtils.isNotBlank(param.getEmail()) ? param.getEmail() : "");
        user.setSex(sexCode);
        List<User> users = convertUser(Lists.newArrayList(user));
        userMapper.insertSelective(users.get(0));

        return users.get(0);
    }

    private Map<Long, List<CourseDTO>> getUniversityCourse(List<Integer> courseDirectionHideIds) {

        Map<Long, List<CourseDTO>> resultMap = Maps.newHashMap();

        // 获取勾选配置
        List<SystemConfig> systemConfigs = systemConfigService.listConfigByKeys(
                Lists.newArrayList(SystemConfigEnum.SCHOOL_TYPE.getKey()));
        List<Integer> configIds = systemConfigs.stream()
                .filter(systemConfig -> !courseDirectionHideIds.contains(systemConfig.getId()))
                .map(SystemConfig::getId)
                .collect(Collectors.toList());

        // 获取页签的课程
        List<Long> courseIds = Lists.newArrayList();
        Map<Long, List<CourseExtend>> map = null;
        if (CollectionUtils.isNotEmpty(configIds)) {
            List<Direction> directions = directionService.queryDirection(configIds, null);
            if (CollectionUtils.isNotEmpty(directions)) {
                List<CourseExtend> courseExtends = directionService.queryCourseExtend(
                        directions.stream().map(Direction::getId).collect(Collectors.toList()), null);
                map = BeanUtil.aggByKeyToList("directionId", courseExtends);
                courseIds = courseExtends.stream()
                        .map(CourseExtend::getCourseId).distinct().collect(Collectors.toList());
            }
        }

        // 拿这些课程去course_basic查预置课程
        List<CourseDTO> courseDTOS = courseService.listCourse(
                Lists.newArrayList(CourseStatusEnum.SHARED.getCode()),
                true, true, null, courseIds);
        if (MapUtils.isEmpty(map)) {
            resultMap.put(1L, courseDTOS);
            return resultMap;
        }

        map.forEach((directionId, courseExtends) -> {
            List<CourseDTO> result = Lists.newArrayList();
            List<Long> list = courseExtends.stream().map(CourseExtend::getCourseId).collect(Collectors.toList());
            List<CourseDTO> courses = courseDTOS.stream()
                    .filter(courseDTO -> list.contains(courseDTO.getId())).collect(Collectors.toList());
            List<CourseDTO> data = courses.stream().filter(courseDTO -> courseDTO.getType() != null)
                    .collect(Collectors.toList());
            Map<Integer, List<CourseDTO>> typeMap = BeanUtil.aggByKeyToList("type", data);
            if (CollectionUtils.isNotEmpty(typeMap.get(CourseTypeEnum.CORE.getCode()))) {
                result.add(typeMap.get(CourseTypeEnum.CORE.getCode()).get(0));
            }
            if (CollectionUtils.isNotEmpty(typeMap.get(CourseTypeEnum.EXPAND.getCode()))) {
                result.add(typeMap.get(CourseTypeEnum.EXPAND.getCode()).get(0));
            }
            if (data.size() != courses.size()) {
                result.add(courses.stream().filter(courseDTO -> courseDTO.getType() == null)
                        .collect(Collectors.toList()).get(0));
            }
            if (CollectionUtils.isNotEmpty(result)) {
                resultMap.put(directionId, result);
            }

        });

        return resultMap;
    }

    private List<UserDirectionDTO> convertUserDirection(List<SystemConfig> configs, List<Integer> status) {
        List<UserDirectionDTO> result = Lists.newArrayList();
        configs.forEach(config -> {
            UserDirectionDTO direction = new UserDirectionDTO();
            direction.setId(config.getId());
            direction.setKeyValue(config.getKeyValue());
            direction.setRemark(config.getRemark());
            direction.setShow(status.contains(config.getId()) ? true : false);
            result.add(direction);
        });
        return result;
    }

    private CreateUserParam convertStudent(int i) {
        CreateUserParam userParam = new CreateUserParam();
        userParam.setUserNumber(setUserNumber(i));
        userParam.setPassword(userParam.getUserNumber());
        userParam.setName(RandomUtil.randomEle(NAMES) + "同学");
        userParam.setRoleName(RoleEnum.STUDENT.getRoleName());
        return userParam;
    }

}
